package com.pandas.community.service;

import com.pandas.community.Utils.CommunityConstant;
import com.pandas.community.Utils.RedisKeyUtil;
import com.pandas.community.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowService implements CommunityConstant {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    //关注功能
    public void follow(int userid, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {

                String followeeKey = RedisKeyUtil.getFolloweeKey(userid, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                redisOperations.multi();
                redisOperations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                redisOperations.opsForZSet().add(followerKey, userid, System.currentTimeMillis());

                return redisOperations.exec();
            }
        });
    }

    //取消关注
    public void unfollow(int userid, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {

                String followeeKey = RedisKeyUtil.getFolloweeKey(userid, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                redisOperations.multi();
                redisOperations.opsForZSet().remove(followeeKey, entityId);
                redisOperations.opsForZSet().remove(followerKey, userid);
                return redisOperations.exec();
            }
        });
    }

    // 关注的人数
    public long getFolloweeCount(int userid, int entityType){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userid, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    // 跟随者人数
    public long getFollowerCount(int entityType, int entityId){
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }


    //查询当前用户是否已关注实体
    public boolean hasFollowed(int userid, int entityType, int entityId){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userid, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

    //查询用户的关注人
    public List<Map<String, Object>> getFollowees(int userid, int offset, int limit){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userid, ENTITY_TYPE_USER);
        Set<Integer> followeeIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);

        if(followeeIds == null) return null;

        List<Map<String, Object>> followees = new ArrayList<>();
        for(int followeeId : followeeIds){
            Map<String, Object> map = new HashMap<>();
            User followeeUser = userService.selectById(followeeId);
            map.put("followeeUser", followeeUser);
            Double score = redisTemplate.opsForZSet().score(followeeKey, followeeId);
            map.put("followTime", new Date(score.longValue()));
            followees.add(map);
        }
        return followees;
    }

    //查询用户的粉丝
    public List<Map<String, Object>> getFollowers(int userid, int offset, int limit){
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER,userid);
        Set<Integer> followerIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);

        if(followerIds == null) return null;

        List<Map<String, Object>> followers = new ArrayList<>();
        for(int followerId : followerIds){
            Map<String, Object> map = new HashMap<>();
            User followerUser = userService.selectById(followerId);
            map.put("followerUser", followerUser);
            Double score = redisTemplate.opsForZSet().score(followerKey, followerId);
            map.put("followTime", new Date(score.longValue()));
            followers.add(map);
        }
        return followers;
    }

}

